﻿using GFXHelper.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace GFXHelper
{
    public partial class FormMain : Form
    {
        //Variablen
        string anwendungsPfad = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        ServerSettings settings;
        string slash = Path.DirectorySeparatorChar.ToString(); //Slash für plattformübergreifende Programme (siehe Mono)

        private static bool IsRunningOnMono
        {
            get
            {
                return (Type.GetType("Mono.Runtime") != null);
            }
        }

        public FormMain()
        {
            InitializeComponent();
            if (IsRunningOnMono || !File.Exists(this.anwendungsPfad + this.slash + "IE_Functions.dll"))
            {
                this.buttonIE.Hide();
                this.labelSelectBrowser.Hide();
                this.buttonFirefox.Size = new System.Drawing.Size(267, 23);
                this.buttonFirefox.Text = Resources.start;
            }
            if (File.Exists(this.anwendungsPfad + this.slash + "ServerSettings.xml"))
            {
                this.settings = ServerEinstellungenLaden(this.anwendungsPfad + this.slash + "ServerSettings.xml");
            }
            else
            {
                ServerEinstellungenSpeichern(this.anwendungsPfad + this.slash + "ServerSettings.xml");
                this.settings = new ServerSettings(); // Da die Datei ja erst eben gerade erstellt wurde, ist das also kein Problem...
            }
        }

        private void buttonFirefox_Click(object sender, EventArgs e)
        {
            string firefoxAppData;
            if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix)
            {
                firefoxAppData = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + this.slash + ".mozilla" + this.slash + "Firefox" + this.slash;
            }
            else
            {
                firefoxAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + this.slash + "Mozilla" + this.slash + "Firefox" + this.slash;
            }

            string profilesIniPath; //Pfad zur "profiles.ini"
            profilesIniPath = firefoxAppData + "profiles.ini";

            //Wenn die Datei nicht existiert, können wir nicht weiter arbeiten...
            if (!File.Exists(profilesIniPath))
            {
                MessageBox.Show(Resources.profilesIniDoesntExist, Resources.error, MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }

            StreamReader profilesIniRead = new StreamReader(profilesIniPath, Encoding.Default); //Erstellt einen StreamReader
            string profilesIniText = profilesIniRead.ReadToEnd(); //Liest den kompletten Inhalt
            profilesIniRead.Close(); //Datei wieder freigeben

            bool[] profileIsRelative = new bool[0]; //Erstellt ein Integer-Array mit der Angabe bei einem relativen Pfad
            string[] profilNamen = new string[0]; //Erstellt ein String-Array mit den Namen
            string[] profilVerzeichnisse = new string[0]; //Erstellt ein String-Array mit dem Pfad
            while (profilesIniText.IndexOf("[Profile") != -1) //profiles.ini parsen
            {
                Array.Resize<string>(ref profilNamen, profilNamen.Length + 1);
                profilesIniText = profilesIniText.Substring(profilesIniText.IndexOf("Name=") + 5);
                profilNamen[profilNamen.Length - 1] = profilesIniText.Substring(0, profilesIniText.IndexOf("\r\n")); //Liest den Namen und speichert ihn

                Array.Resize<bool>(ref profileIsRelative, profileIsRelative.Length + 1);
                profilesIniText = profilesIniText.Substring(profilesIniText.IndexOf("IsRelative=") + 11);
                profileIsRelative[profileIsRelative.Length - 1] = Int32.Parse(profilesIniText.Substring(0, profilesIniText.IndexOf("\r\n"))).ToBool(); //Liest ab, ob der Pfad relativ zum Profilpfad ist

                Array.Resize<string>(ref profilVerzeichnisse, profilVerzeichnisse.Length + 1);
                profilesIniText = profilesIniText.Substring(profilesIniText.IndexOf("Path=") + 5);
                profilVerzeichnisse[profilVerzeichnisse.Length - 1] = profilesIniText.Substring(0, profilesIniText.IndexOf("\r\n")); //Pfad lesen
            }

            //Jetzt beginnt der eigentliche Vorgang für alle Profile, damit wir auch wirklich bei nur einem Klick bleiben...
            //Wozu sollten wir noch dieses und jenes Fenster anzeigen, welches die Nutzer nur noch mehr verwirrt?
            //Außerdem tut Wurzelimperium ja nichts...
            for (int i = 0; i < profilNamen.Length; i++)
            {
                string profilPath = String.Empty;
                if (profileIsRelative[i] == true)
                {
                    profilPath = firefoxAppData + profilVerzeichnisse[i].Replace('/', Path.DirectorySeparatorChar);
                }
                else
                {
                    profilPath = profilVerzeichnisse[i].Replace('/', Path.DirectorySeparatorChar);
                }
                string userJSPath = profilPath + this.slash + "user.js"; //Den user.js-Pfad bilden

                //Die Datei wird zum Schreiben geöffnet - alle Zeilen werden hinten drangehängt (dafür dieses "true")
                StreamWriter userJSWriter = new StreamWriter(userJSPath, true, Encoding.Default);

                //Die erste Zeile...
                userJSWriter.WriteLine("user_pref(\"capability.policy.policynames\", \"wurzelgfx\");");
                //Die Server...
                List<string> urls = new List<string>(this.settings.Server.CountNumbers());
                for (int j = 0; j < this.settings.Adressen.Length; j++)
                {
                    for (int k = 1; k <= this.settings.Server[j]; k++)
                    {
                        //Mit dieser Zeile wird eine Adresse erstellt - simpel, oder?
                        urls.Add("http://s" + k.ToString() + "." + this.settings.Adressen[j]);
                    }
                }

                userJSWriter.WriteLine("user_pref(\"capability.policy.wurzelgfx.sites\", \"" + String.Join(" ", urls.ToArray()) + "\");");
                //Die letzte Zeile schreiben
                userJSWriter.WriteLine("user_pref(\"capability.policy.wurzelgfx.checkloaduri.enabled\", \"allAccess\");");
                //Alles auf die Festplatte schreiben
                userJSWriter.Close();
            }
            MessageBox.Show(Resources.done, Resources.information, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void buttonIE_Click(object sender, EventArgs e)
        {
            // Doppelt hält besser
            if (!IsRunningOnMono && File.Exists(this.anwendungsPfad + this.slash + "IE_Functions.dll"))
            {
                Assembly ie_functions = Assembly.LoadFile(this.anwendungsPfad + this.slash + "IE_Functions.dll");
                MethodInfo create_entries = ie_functions.GetType("IE_Functions.EntryCreator", true).GetMethod("CreateEntries");
                create_entries.Invoke(null, new object[] { this.settings.Adressen, this.settings.Server });
            }
        }

        private ServerSettings ServerEinstellungenLaden(string pfad)
        {
            XmlSerializer reader = new XmlSerializer(typeof(ServerSettings), "ServerSettings");
            StreamReader file = new StreamReader(pfad, Encoding.Default);
            ServerSettings settings = (ServerSettings)reader.Deserialize(file);
            file.Close();
            return settings;
        }

        private void ServerEinstellungenSpeichern(string pfad)
        {
            ServerSettings settings = new ServerSettings();
            XmlSerializer writer = new XmlSerializer(typeof(ServerSettings), "ServerSettings");
            StreamWriter file = new StreamWriter(pfad, false, Encoding.Default);
            writer.Serialize(file, settings);
            file.Close();
        }
    }
}
